package com.taysear.parcel;

import java.util.Date;
import java.util.HashMap;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;

import com.taysear.parcel.domain.User;
import com.taysear.parcel.util.Constants;
import com.taysear.parcel.util.tpt.Captcha;
import com.vaadin.Application;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.data.util.filter.And;
import com.vaadin.data.util.filter.Compare.Equal;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Panel;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.Runo;

/**
 * <code>LoginScreen</code> is used to create the login form of the application.
 * 
 * @author Abdullahi
 */
@SuppressWarnings("serial")
public class LoginScreen2 extends VerticalLayout {

	private Captcha captcha = null;
	HorizontalLayout captchaLayout = new HorizontalLayout();
	TextField captchaResult = new TextField("Captcha result");
	private int wrongPasswordTrials = 1;
	ParcelApplication app = null;
	
	public LoginScreen2(ParcelApplication app) {
		this.app = app;
		setSizeFull();
		
		Component loginPanel = getLoginForm();
		
		addComponent(loginPanel);
		setComponentAlignment(loginPanel, Alignment.MIDDLE_CENTER);

	}
	
	@Override
	public void attach() {
		super.attach();
		captcha = new Captcha(app);
		
		captchaLayout.setSpacing(true);
		captchaLayout.addComponent(captcha);
		captchaLayout.addComponent(getGenerateCaptchaCodeButton());
		
	}
	
	private Button getGenerateCaptchaCodeButton() {
		Button button = new Button("Generate captcha");
		button.addStyleName("greenButton");
		button.setDisableOnClick(true);
		button.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	captcha.generateCaptchaCode(5);
		    	event.getButton().setEnabled(true);
		    }
		});
		
		return button;
	}
	
	private Component getLoginForm() {
		// The application caption is shown in the caption bar of the browser window.
		this.app.getMainWindow().setCaption("Parcels");
		setSizeFull();
		
		Panel panel = new Panel("Login");
		panel.addStyleName(Runo.PANEL_LIGHT);
		panel.setWidth("400px");
		
		final Form form = new Form();
		form.setHeight("220px");
		
		TextField userName = new TextField("Username");
		userName.focus();
		userName.setRequired(true);
		userName.setRequiredError("This field is required");
		//userName.setValue("admin");
		form.addField("username", userName);
		
		PasswordField password = new PasswordField("Password");
		password.setRequired(true);
		password.setRequiredError("This field is required");
		//password.setValue("admin");
		//password.setValue("Awale##aaxc973");
		form.addField("password", password);
		
		captchaLayout.setVisible(false);
		form.getLayout().addComponent(captchaLayout);
		
		captchaResult.setVisible(false);
		form.addField("captchaResult", captchaResult);
		
		Button login = getLoginButton(form);
		form.addField("", login);
		
		return form;
	}
	
	/**
	 * Get a button that logs the user in.
	 * 
	 * @return Button
	 */
	private Button getLoginButton(final Form form) {
		Button button = new Button("Login");
		button.addStyleName("blueButton");
		button.setDisableOnClick(true);
		button.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	String username = form.getField("username").toString();
				String password = User.hash(form.getField("password").toString());
				ParcelApplication app = (ParcelApplication) getApplication();

				String captchResultString = form.getField("captchaResult").getValue().toString();
	    		String captchaCode = captcha.getCaptchaCode();
	    		if(wrongPasswordTrials <= 3 | (wrongPasswordTrials > 3 && captchResultString.equalsIgnoreCase(captchaCode))) {
					try {
						ParcelApplication.getInstance().login(username, password);
						And and = new And(new Equal("username",username), new Equal("password",password));
						JPAContainer<User> users = JPAContainerFactory.make(User.class, app.PERSISTENCE_UNIT);
						users.addContainerFilter(and);
						User user = users.getItem(users.firstItemId()).getEntity();
						Boolean employeeStatusInActive = user.getEmployee().getEmployeeStatus().getEmployeeStatusId() == Constants.EMPLOYEE_STATUS_IN_ACTIVE;
						
						Boolean employmentTerminated = user.getEmployee().getTerminatedDate() != null;
						if(employmentTerminated) {
							Date now = app.getDateWithoutTime(new Date());
							Date dateEndOfEmployment = user.getEmployee().getTerminatedDate();
							int dateCompare = dateEndOfEmployment.compareTo(now);
							employmentTerminated = dateCompare == -1;
						}
						
						Boolean stationStatusInActive = user.getEmployee().getStation().getStationStatus().getStationStatusId() == Constants.STATION_STATUS_IN_ACTIVE;
						Boolean substationStatusInActive = user.getEmployee().getSubstation().getStationStatus().getStationStatusId() == Constants.STATION_STATUS_IN_ACTIVE;
						if(employeeStatusInActive | employmentTerminated |stationStatusInActive | substationStatusInActive)
							throw new Exception("Employee, station or substation status is inactive");
						ParcelApplication.getInstance().setUser(user);
						// Switch to the protected view
						app.getMainLayout().loadMenuAndUserInfo();
					} catch (UnknownAccountException uae) {
						app.showNotification("Invalid User");
						checkWrongPasswordTrials();
					} catch (IncorrectCredentialsException ice) {
						app.showNotification("Invalid User");
						checkWrongPasswordTrials();
					} catch (LockedAccountException lae) {
						app.showNotification("Invalid User");
						checkWrongPasswordTrials();
					} catch (ExcessiveAttemptsException eae) {
						app.showNotification("Invalid User");
						checkWrongPasswordTrials();
					} catch (AuthenticationException ae) {
						app.showNotification("Invalid User");
						checkWrongPasswordTrials();
					} catch (Exception ex) {
						app.showNotification("Exception " + ex.getMessage());
						checkWrongPasswordTrials();
					}
	    		}else {
	    			app.showNotification("Invalid captcha code");
	    		}
	    		event.getButton().setEnabled(true);
		    } 
		});
		return button;
	}
	
	private void checkWrongPasswordTrials() {
		if(wrongPasswordTrials == 3) {
			captchaLayout.setVisible(true);
			captchaResult.setVisible(true);
			captchaResult.setRequired(true);
			captchaResult.setRequiredError("This field is required");
			
			wrongPasswordTrials += 1;
		} else if(wrongPasswordTrials <= 2) {
			wrongPasswordTrials += 1;
		}
	}
}
